package com.cloudbroker.bcs.platform.ltb.common.payUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloudbroker.bcs.platform.ltb.common.payUtil.bean.OrderRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
//import com.yunpay.demo.pay.bean.OrderResponse;

/**
 * @ClassName HttpUtils
 * @Description HTTP工具类
 * @author yangchun yangchun@hundsun.com
 * 
 *         <pre>
 *         说明： 以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
 *         该代码仅供学习和研究三峡付接口使用，只是提供一个
 * @date 2014年10月16日
 */
public class HttpUtils {

    private static final String certFile = "apiclient_cert.p12";
    private static final String yunpayFile ="yunpay.cer";
    private static final String certPasswd ="1262260201";
    public static final String gateway_url = "http://test.epay.hsjry.com:2800/eis/yunpay";
    public static final String epay_wallet_pay = "/epay_wallet_pay";//钱包支付申请
    public static final String epay_query_orders = "/epay_query_orders";//批量订单查询
    public static String POST = "post";
    private static final String CHARSET = "UTF-8";

    /** 连接超时 */
    private static final int CONNECT_TIMEOUT = 60 * 1000;

    /** 请求超时 */
    private static final int SO_TIMEOUT = 60 * 1000;

    private static Logger loggger = LoggerFactory.getLogger(HttpUtils.class);

    private HttpUtils() {
    }

    /**
     * Post请求
     * 
     * @param url
     * @param paraMap
     * @return
     * @throws Exception
     */
    public static String doPost(String url, Map<String, Object> paraMap) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse resp = null;
        String rtnValue = null;
        try {
            if (url.startsWith("https")) {
                // 获取https安全客户端
                httpClient = HttpUtils.getHttpsClient();
            } else {
                httpClient = HttpClients.createDefault();
            }

            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            if (null != paraMap && paraMap.size() > 0) {
                for (Entry<String, Object> entry : paraMap.entrySet()) {
                    if (null!=entry.getValue()) {
                        list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                    }
                }
            }

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SO_TIMEOUT)
                    .setConnectTimeout(CONNECT_TIMEOUT).build();// 设置请求和传输超时时间
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(new UrlEncodedFormEntity(list, CHARSET));
            resp = httpClient.execute(httpPost);
            rtnValue = EntityUtils.toString(resp.getEntity(), CHARSET);

        } catch (Exception e) {
            loggger.error(e.getMessage());
            throw e;
        } finally {
            if (null != resp) {
                resp.close();
            }
            if (null != httpClient) {
                httpClient.close();
            }
        }

        return rtnValue;
    }

    /**
     * 
     * @Method: getHttpsClient
     * @Description: https 单向验证
     * @param @return
     * @param @throws SanxiaPayBizException
     * @return HttpClient
     * @throws
     */
    public static CloseableHttpClient getHttpsClient() throws Exception {
        try {
            TrustManager[] trustManagers = new TrustManager[] { new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString)
                        throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString)
                        throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            } };
            SSLContext sslContext = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
            sslContext.init(new KeyManager[0], trustManagers, new SecureRandom());
            SSLContext.setDefault(sslContext);
            sslContext.init(null, trustManagers, null);
            SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            HttpClientBuilder clientBuilder = HttpClients.custom().setSSLSocketFactory(connectionSocketFactory);
            clientBuilder.setRedirectStrategy(new LaxRedirectStrategy());
            CloseableHttpClient httpClient = clientBuilder.build();
            return httpClient;
        } catch (Exception e) {
            throw new Exception("http client 远程连接失败", e);
        }
    }

    public static String post(Map<String, Object> msgs, String url) throws ClientProtocolException,
            UnknownHostException, IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpPost request = new HttpPost(url);
            List<NameValuePair> valuePairs = new ArrayList<NameValuePair>();
            if (null != msgs) {
                for (Entry<String, Object> entry : msgs.entrySet()) {
                    valuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
            }
            request.setEntity(new UrlEncodedFormEntity(valuePairs, CHARSET));
            CloseableHttpResponse resp = httpClient.execute(request);
            return EntityUtils.toString(resp.getEntity(), CHARSET);
        } finally {
            httpClient.close();
        }
    }

    public static String get(Map<String, Object> msgs, String url) throws ClientProtocolException,
            UnknownHostException, IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            List<NameValuePair> valuePairs = new ArrayList<NameValuePair>();
            if (null != msgs) {
                for (Entry<String, Object> entry : msgs.entrySet()) {
                    valuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
            }
            // EntityUtils.toString(new UrlEncodedFormEntity(valuePairs),
            // CHARSET);
            url = url + "?" + URLEncodedUtils.format(valuePairs, CHARSET);
            HttpGet request = new HttpGet(url);
            CloseableHttpResponse resp = httpClient.execute(request);
            return EntityUtils.toString(resp.getEntity(), CHARSET);
        } finally {
            httpClient.close();
        }
    }

    public static String yunpayYeePayGet(Map<String, Object> msgs, String url) throws ClientProtocolException,
            UnknownHostException, IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            List<NameValuePair> valuePairs = new ArrayList<NameValuePair>();
            if (null != msgs) {
                for (Entry<String, Object> entry : msgs.entrySet()) {
                    valuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
            }
            // EntityUtils.toString(new UrlEncodedFormEntity(valuePairs),
            // CHARSET);
            url = url + "&" + URLEncodedUtils.format(valuePairs, CHARSET);
            HttpGet request = new HttpGet(url);
            CloseableHttpResponse resp = httpClient.execute(request);
            return EntityUtils.toString(resp.getEntity(), CHARSET);
        } finally {
            httpClient.close();
        }
    }

    /*
	 * 摘要+加签+发送
	 */
    public static String proceed(OrderRequest request, String method) throws Exception {
        String extend_info=request.getExtend_info();
        Map<String, Object> map = checkAndInsert (request);
        String post_url = HttpUtils.gateway_url + "/" + method;
        System.out.println ("请求地址:" + post_url);
        String source = EncryptUtil.sortSource (map); // 原文排序
        System.out.println ("加签原文:" + source);
        source = SHA256Util.getSHA256 (source); // 对原文做摘要算法
        System.out.println ("加签摘要:" + source);
        //获取私钥证书
        //对摘要加签
        String sign = RSAUtils.sign (source.getBytes (), certFile, certPasswd, null);
        System.out.println ("签名应答:" + sign);
        map.put ("cert_sign", sign);
        map.remove("extend_info_list");
        map.put("extend_info", extend_info);
        String resp;
        try {
            resp = HttpUtils.doPost (post_url, map);
            boolean result = false;
            if ("epay_apply_check_file".equals (method) || "epay_query_orders".equals (method)) {
                if (resp.contains ("\n")) {
                    dealWithFile (resp);
                } else {
                    return resp;
                }
            } else {
                String cert_sign = null; //获取返回的报文中的签名串
                JSONObject jsonObj = (JSONObject) JSON.parse(resp);
                /*
                 * 成功响应报文格式为{data:[{"pay_status":"3","cert_sign":"sign"}]}
                 * 失败响应报文格式为{"error_no":"999999","error_info":"error","error_code":"999999","error_extinfo":"error","cert_sign":"sign"}
                 */
                if (jsonObj.getJSONArray("data") != null) {
                    jsonObj = jsonObj.getJSONArray("data").getJSONObject(0);
                }
                cert_sign = jsonObj.getString("cert_sign");
                jsonObj.remove("cert_sign");
                /* 拼装签名要素，排序 */
                String content = EncryptUtil.sortSource (jsonObj);
                System.out.println("验签原文：" + content);
				/* 签名要素摘要，摘要算法SHA-256 */
                content = SHA256Util.getSHA256 (content);
                System.out.println("验签摘要：" + content);
				/* 验签 ，签名算法SHA1withRSA*/
                result = RSAUtils.verifyByCert (content.getBytes ("UTF-8"), yunpayFile, cert_sign);
                System.out.println("验签结果：" + result);
            }

            System.out.println("doPost应答：" + resp);
        }catch (Exception e) {
            System.out.println("doPost失败"+e);
            return "doPost失败" + e;
        }
        return resp;
    }

//    /**
//     * 签名
//     * @param request
//     * @return
//     */
//    private String sign(OrderRequest request) throws Exception {
//        Map<String, Object> map = checkAndInsert (request);
//        String source = EncryptUtil.sortSource (map); // 原文排序
//        System.out.println ("加签原文:" + source);
//        source = SHA256Util.getSHA256 (source); // 对原文做摘要算法
//        System.out.println ("加签摘要:" + source);
//        //获取私钥证书
//        String key_file = PayBizServiceImpl.class.getClassLoader ().getResource (certFile).getPath ();
//        //对摘要加签
//        String sign =  RSAUtils.sign (source.getBytes (), key_file, certPasswd, null);
//        System.out.println ("签名应答:" + sign);
//        return sign;
//    }

    /**
     * @return
     * @Method checkAndInsert
     * @Description 检查提交的表单，非空则插入到map中
     * @param @field
     * @return void
     * @throws
     */
    protected static Map<String, Object> checkAndInsert(OrderRequest request) {

        if (null != request.getDetail () && !"".equals (request.getDetail ())) {
            @SuppressWarnings ("unchecked")
            List<OrderRequest> list = JSONObject.parseObject (request.getDetail (), List.class);
            request.setDetails (list);
            request.setDetail (null);
        }
        if (null != request.getExtend_info() && !"".equals (request.getExtend_info ())) {
            @SuppressWarnings ("unchecked")
            List<OrderRequest> list = JSONObject.parseObject (request.getExtend_info(), List.class);
            request.setExtend_info_list(list);
            request.setExtend_info (null);
        }
        @SuppressWarnings ("unchecked")
        Map<String, Object> map = (Map<String, Object>) JSONObject.parse (JSONObject.toJSONString (request));

        return map;
    }

    /**
     * method comments here
     * @param resp
     * @throws Exception
     * @throws UnsupportedEncodingException
     * @throws IOException
     */
    protected static void dealWithFile(String resp) throws Exception, UnsupportedEncodingException, IOException {
//        boolean result;
//        String content = resp.substring (0, resp.lastIndexOf ("\n"));
//        String signStr = resp.substring (resp.lastIndexOf ("\n") + 1, resp.length ());
//        result = RSAUtils.verifyByCert (SHA256Util.getSHA256 (content).getBytes ("UTF-8"), HttpUtils.class.getClassLoader ()
//                .getResource ("/resource/yunpay.cer").getPath (), signStr);
//        System.out.println("验签结果:" + result);
    }



//    public static String doPostWithXML(String protocal, String url, String xml) throws Exception {
//        CloseableHttpClient httpClient = null;
//        CloseableHttpResponse resp = null;
//        String rtnValue = null;
//        try {
//            if (protocal.equals("http")) {
//                httpClient = HttpClients.createDefault();
//            } else {
//                // 获取https安全客户端
//                httpClient = HttpUtils.getHttpsClient();
//            }
//
//            HttpPost httpPost = new HttpPost(url);
//
//            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SO_TIMEOUT)
//                    .setConnectTimeout(CONNECT_TIMEOUT).build();// 设置请求和传输超时时间
//            httpPost.setConfig(requestConfig);
//
//            // httpPost.setEntity(new StringEntity(xml));
//            httpPost.setEntity(new StringEntity(xml, CHARSET));
//            httpPost.setHeader("Content-type", "text/xml");
//
//            resp = httpClient.execute(httpPost);
//            rtnValue = EntityUtils.toString(resp.getEntity(), CHARSET);
//
//            String sign = "";
//            OrderResponse orderResp = null;
//            if ((rtnValue.indexOf("</Sign>") - rtnValue.indexOf("<Sign>")) > 5)
//                sign = rtnValue.substring(rtnValue.indexOf("<Sign>") + 6, rtnValue.indexOf("</Sign>"));
//
//            if ((rtnValue.indexOf("</Response>") - rtnValue.indexOf("<Response>")) > 9) {
//                String respString = rtnValue.substring(rtnValue.indexOf("<Response>"),
//                        rtnValue.indexOf("</Response>") + 11);
//                respString = respString.replace("Response", OrderResponse.class.getName());
//                orderResp = (OrderResponse) XMLUtil.fromXML(respString);
//            }
//            // 排序
//            String source = EncryptUtil.sortSource(JSONObject.parseObject(JSONObject.toJSONString(orderResp)));
//            loggger.info("ori:" + source);
//            source = SHA256Util.getSHA256(source); // 对原文做摘要算法(SHA256)
//            loggger.info("SHA ori:" + source);
//            boolean isOK = false;
//            isOK = RSAUtils.verifyByCert(source.getBytes(),
//                    HttpUtils.class.getClassLoader().getResource("/resource/yunpay.cer").getPath(), sign);
//            loggger.info("验证签名：" + isOK);
//            if (!isOK) {
//                throw new Exception("三峡付返回数据签名不通过");
//            }
//        } catch (Exception e) {
//            loggger.error(e.getMessage());
//            return rtnValue;
//        } finally {
//            if (null != resp) {
//                resp.close();
//            }
//            if (null != httpClient) {
//                httpClient.close();
//            }
//        }
//
//        return rtnValue;
//    }
}
